package ceneax.app.lib.qrscan.engine;

import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.media.Image;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.camera.core.ImageProxy;

import com.google.mlkit.vision.barcode.BarcodeScanner;
import com.google.mlkit.vision.barcode.BarcodeScannerOptions;
import com.google.mlkit.vision.barcode.BarcodeScanning;
import com.google.mlkit.vision.barcode.common.Barcode;
import com.google.mlkit.vision.common.InputImage;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import ceneax.app.lib.qrscan.arch.QRAnalyzer;
import ceneax.app.lib.qrscan.bean.ParseResult;
import ceneax.app.lib.qrscan.util.CoderUtil;
import ceneax.app.lib.qrscan.util.ImageUtil;

public class MLKitAnalyzer extends QRAnalyzer {
    // 是否扫描完毕
    private boolean mScanFinished = false;

    private static final int SCAN_TIMEOUT = 300;
    // 解析器
    private BarcodeScanner mScanner;
    private BarcodeScannerOptions mOptions;
    private List<String> scanResults;
    private List<ParseResult> mParseResults;
    private Handler mHander;
    private Bitmap mBitmap;

    public MLKitAnalyzer() {
        mOptions = new BarcodeScannerOptions.Builder()
                .setBarcodeFormats(CoderUtil.defaultMLKitCoder())
                .build();
        mScanner = BarcodeScanning.getClient(mOptions);
        scanResults = new ArrayList<>();
        mParseResults = new ArrayList<>();
        mHander = new Handler(Looper.getMainLooper());
    }

    public void setBarcodeFormats(int formats, int... moreFormats) {
        mOptions = new BarcodeScannerOptions.Builder()
                .setBarcodeFormats(formats, moreFormats)
                .build();
        mScanner = BarcodeScanning.getClient(mOptions);
    }

    @Override
    public void analyze(@NonNull ImageProxy image) {
        long startTime = System.currentTimeMillis();

        if (mScanFinished) {
            image.close();
            return;
        }

        @SuppressLint("UnsafeOptInUsageError") Image mediaImage = image.getImage();
        if (mediaImage == null) {
            image.close();
            return;
        }

        InputImage inputImage = InputImage.fromMediaImage(mediaImage, image.getImageInfo().getRotationDegrees());

        // 解析二维码
        mScanner.process(inputImage)
                .addOnSuccessListener(barcodes -> {
                    List<ParseResult> results = transResults(barcodes, inputImage.getRotationDegrees(),
                            System.currentTimeMillis() - startTime);
                    if (results.isEmpty()) {
                        // 未识别到二维码，继续处理下一帧图像
                        return;
                    }
                    mBitmap = ImageUtil.rotateBitmap(ImageUtil.yuvToBitmap(image), inputImage.getRotationDegrees());
                    if (mScanFinished) {
                        return;
                    }
                    if (scanResults.size() == 0) {
                        startHandlerDelay();
                        for (ParseResult result : results) {
                            scanResults.add(result.getContent());
                        }
                        mParseResults.addAll(results);
                    } else {
                        for (ParseResult result : results) {
                            if (!scanResults.contains(result.getContent())) {
                                scanResults.add(result.getContent());
                                mParseResults.add(result);
                            }
                        }
                    }

//                    // 识别到结果，执行回调
//                    onResult(ImageUtil.rotateBitmap(ImageUtil.yuvToBitmap(image), inputImage.getRotationDegrees()),
//                            results.toArray(new ParseResult[0]));
//                    // 停止接收图像帧数据
//                    mScanFinished = true;
                })
                .addOnCompleteListener(task -> image.close());
    }

    public void startHandlerDelay() {
        Log.e("MLKitAnalyzer", "startHandlerDelay");
        mHander.postDelayed(() -> {
            onAnalyzeResult();
            Log.e("MLKitAnalyzer", "stopHandlerDelay");
        }, SCAN_TIMEOUT);
    }

    public void onAnalyzeResult() {
        Log.e("MLKitAnalyzer", "onAnalyzeResult scanResults:" + scanResults);
        // 识别到结果，执行回调
        onResult(mBitmap, mParseResults.toArray(new ParseResult[0]));
        // 停止接收图像帧数据
        mScanFinished = true;
        scanResults.clear();
        mParseResults.clear();
    }

    @Override
    public void rescan(long delayMillis) {
        runOnUIDelay(delayMillis, () -> mScanFinished = false);
    }

    public static List<ParseResult> transResults(List<Barcode> barcodes, int rotationDegrees, long tookMs) {
        List<ParseResult> results = new ArrayList<>();
        for (int i = 0; i < barcodes.size(); i++) {
            if (barcodes.get(i).getRawValue() == null) {
                continue;
            }
            results.add(new ParseResult(
//                    ImageUtil.rotateRect(barcodes.get(i).getBoundingBox(), rotationDegrees),
                    barcodes.get(i).getBoundingBox(),
                    Objects.requireNonNull(barcodes.get(i).getRawValue()),
                    tookMs
            ));
        }
        return results;
    }
}
